﻿/*******************************************************************************
 * AAEngine
 * Copyright (c) 2010 Mike Jarosch
 *
 * Original source PushButton Engine:
 * Copyright (C) 2009 PushButton Labs, LLC
 * For more information see http://www.pushbuttonengine.com
 *
 * This file is licensed under the terms of the MIT license, which is included
 * in the "MIT License.txt" file at the root directory of this SDK.
 ******************************************************************************/

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using AAEngine.Engine;
using AAEngine.Engine.Resources;

namespace AAEngine.Rendering2D.SpriteSheet
{
    /// <summary>
    /// Handles loading and retrieving data about a sprite sheet to use for rendering.
    /// </summary>
    /// <remarks>
    /// Functionality exists to allow several directions to be specified per frame.
    /// This enables you to, for instance, visually rotate a sprite without rotating
    /// the actual object it belongs to.
    /// Because we may group them in different ways, we distinguish between
    /// "raw frames" and a "frame" which might be made up of multiple directions.
    /// On the subject of sprite sheet order: the divider may alter this, but in
    /// general, frames are numbered left to right, top to bottom. If you have a 4
    /// direction sprite sheet, then 0,1,2,3 will be frame 1, 4,5,6,7 will be 2,
    /// and so on.
    /// </remarks>
    public class SpriteSheetComponent : SpriteContainerComponent
    {
        private string _imageFilename;
        private ImageResource _image;
        private Texture2D[] _forcedBitmaps;
        private ISpriteSheetDivider _divider;

        public override bool IsLoaded
        {
            get
            {
                return _image != null || _forcedBitmaps != null;
            }
        } 

        public string ImageFilename
        {
            get { return _imageFilename; }
            set
            {
                if (_imageFilename != value)
                {
                    if (_image != null)
                    {
                        AAGame.ResourceManager.Unload(_image.Filename);

                        _image = null;
                    }
                    _imageFilename = value;
                    _image = (ImageResource)AAGame.ResourceManager.Load(value, typeof(ImageResource));
                }
            }
        }

        public ImageResource Image
        {
            get { return _image; }
            set 
            {
                _image = value;
                _imageFilename = _image.Filename;
                DeleteFrames();
            }
        }

        public Texture2D ImageData
        {
            get { return _image.ImageData; }
        }

        public ISpriteSheetDivider Divider
        {
            get { return _divider; }
            set 
            {
                _divider = value;
                _divider.OwningSheet = this;
                DeleteFrames();
            }
        }

        protected override Texture2D[] GetSourceFrames()
        {
            if (_forcedBitmaps != null)
            {
                return _forcedBitmaps;
            }

            Texture2D[] frames;

            if (_image == null)
            {
                return null;
            }

            if (_divider == null)
            {
                frames = new Texture2D[1];
                frames[0] = _image.ImageData;
            }
            else
            {
                frames = new Texture2D[_divider.FrameCount];

                for (int i = 0; i < _divider.FrameCount; i++)
                {
                    Rectangle area = _divider.FrameArea(i);
                    Texture2D tex = new Texture2D(_image.ImageData.GraphicsDevice, area.Width, area.Height);
                    Color[] data = new Color[area.Width * area.Height];
                    _image.ImageData.GetData<Color>(0, area, data, 0, data.Length);
                    tex.SetData<Color>(data);
                    frames[i] = tex;
                }
            }

            return frames;
        }

        public void InitializeFromTextureDataArray(Texture2D[] textures)
        {
            _forcedBitmaps = textures;
        }

        public override void OnAdd()
        {
            base.OnAdd();

            if(_image == null && !String.IsNullOrEmpty(_imageFilename))
            {
                _image = (ImageResource)AAGame.ResourceManager.Load(_imageFilename, typeof(ImageResource));
            }
        }

        public override void OnRemove()
        {
            if(_image != null)
            {
                AAGame.ResourceManager.Unload(_image.Filename);
                _image = null;
            }
            base.OnRemove();
        }
    }
}
